﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.Net.DesignByContract;
using System.Reflection;
using Common.Net.Utilities;

namespace ClearUnit.TestRunners.Results
{
    public abstract class MethodRunResult : TestRunResult
    {
        readonly MethodInfo _method;

        public MethodInfo Method
        {
            get { return _method; }
        }

        public Type Fixture
        {
            get { return Method.ReflectedType; }
        }

        public MethodRunResult(MethodInfo method)
        {
            RequireArg.NotNull(method, "_method");

            _method = method;
        }

        public abstract class Run : MethodRunResult
        {
            readonly TimeSpan _length;

            public TimeSpan Length
            {
                get { return _length; }
            } 
            
            public Run(MethodInfo method, TimeSpan length)
                : base(method)
            {
                _length = length;
            }

            public override string ShortDescription
            {
                get { return string.Format("Test {0}.{1} - run and {2} (took {3})", Fixture.Name, Method.Name, GetType().Name, Length.Format()); }
            }

            public sealed class Failed : Run
            {
                readonly Exception _exception;

                public Exception Exception
                {
                    get { return _exception; }
                } 

                public Failed(MethodInfo method, TimeSpan length, Exception exception)
                    : base(method, length)
                {
                    RequireArg.NotNull(exception, "exception");

                    _exception = exception;
                }
            }

            public sealed class Passed : Run
            {
                readonly object _result;

                public object Result
                {
                    get { return _result; }
                } 

                public Passed(MethodInfo method, TimeSpan length, object result)
                    : base(method, length)
                {
                    _result = result;
                }
            }
        }

        public class Skipped : MethodRunResult
        {
            public Skipped(MethodInfo method)
                : base(method)
            {
            }

            public override string ShortDescription
            {
                get { return string.Format("Test {0}.{1} - skipped ({2})", Fixture.Name, Method.Name, GetType().Name); }
            }

            public sealed class ExplicitTest : Skipped
            {
                public ExplicitTest(MethodInfo method)
                    : base(method)
                {
                }
            }
        }
    }
}
